"""
Properties文件处理工具类，提供Properties文件读取、修改等功能
"""

import os
import re
from typing import Dict, Optional, Any, List


class PropertiesUtils:
    """
    Properties文件处理工具类，提供各种Properties文件操作功能
    """
    
    def __init__(self, properties_path: str = None, properties_string: str = None):
        """
        初始化Properties处理工具

        :param properties_path: Properties文件路径，可选
        :param properties_string: Properties字符串，可选
        """
        self.properties = {}
        self.comments = {}  # 存储注释信息
        self.lines = []  # 存储原始行信息
        
        if properties_path:
            self.load_from_file(properties_path)
        elif properties_string:
            self.load_from_string(properties_string)
    
    def load_from_file(self, properties_path: str) -> None:
        """
        从文件加载Properties

        :param properties_path: Properties文件路径
        """
        if not os.path.exists(properties_path):
            raise FileNotFoundError(f"Properties文件不存在: {properties_path}")
        
        with open(properties_path, 'r', encoding='utf-8') as file:
            self.lines = file.readlines()
        
        self._parse_lines()
    
    def load_from_string(self, properties_string: str) -> None:
        """
        从字符串加载Properties

        :param properties_string: Properties字符串
        """
        self.lines = properties_string.splitlines(keepends=True)
        self._parse_lines()
    
    def _parse_lines(self) -> None:
        """
        解析行数据，提取键值对
        """
        self.properties = {}
        
        for line in self.lines:
            line = line.rstrip('\r\n')
            
            # 跳过空行和注释行
            stripped_line = line.strip()
            if not stripped_line or stripped_line.startswith('#') or stripped_line.startswith('!'):
                continue
            
            # 处理键值对，支持 = 和 : 分隔符
            if '=' in line:
                separator = '='
            elif ':' in line:
                separator = ':'
            else:
                # 如果没有标准分隔符，尝试按第一个空白字符分割
                parts = stripped_line.split(None, 1)
                if len(parts) == 2:
                    key, value = parts
                    self.properties[key.strip()] = value.strip()
                continue
                
            # 使用找到的分隔符分割
            parts = line.split(separator, 1)
            key = parts[0].strip()
            value = parts[1].strip() if len(parts) > 1 else ""
            self.properties[key] = value
    
    def _unescape(self, text: str) -> str:
        """
        处理转义字符

        :param text: 需要处理的文本
        :return: 处理后的文本
        """
        # 处理常见的转义字符
        text = text.replace('\\n', '\n')
        text = text.replace('\\r', '\r')
        text = text.replace('\\t', '\t')
        text = text.replace('\\\\', '\\')
        return text
    
    def _escape(self, text: str) -> str:
        """
        添加转义字符

        :param text: 需要处理的文本
        :return: 处理后的文本
        """
        # 转义特殊字符
        text = text.replace('\\', '\\\\')
        text = text.replace('\n', '\\n')
        text = text.replace('\r', '\\r')
        text = text.replace('\t', '\\t')
        return text
    
    def save_to_file(self, properties_path: str, encoding: str = 'utf-8') -> None:
        """
        保存Properties到文件

        :param properties_path: 保存路径
        :param encoding: 编码格式
        """
        # 确保目录存在
        directory = os.path.dirname(properties_path)
        if directory and not os.path.exists(directory):
            os.makedirs(directory)
        
        with open(properties_path, 'w', encoding=encoding) as file:
            file.write(self.to_string())
    
    def get_value(self, key: str, default: str = None) -> str:
        """
        获取指定键的值

        :param key: 键
        :param default: 默认值
        :return: 值
        """
        return self.properties.get(key, default)
    
    def set_value(self, key: str, value: str, comment: str = None) -> None:
        """
        设置键值对

        :param key: 键
        :param value: 值
        :param comment: 注释（可选，当前版本暂不支持）
        """
        self.properties[key] = value
    
    def remove_key(self, key: str) -> bool:
        """
        删除指定键

        :param key: 键
        :return: 是否删除成功
        """
        if key in self.properties:
            del self.properties[key]
            return True
        return False
    
    def has_key(self, key: str) -> bool:
        """
        检查键是否存在

        :param key: 键
        :return: 键是否存在
        """
        return key in self.properties
    
    def get_keys(self) -> List[str]:
        """
        获取所有键

        :return: 键列表
        """
        return list(self.properties.keys())
    
    def get_properties(self) -> Dict[str, str]:
        """
        获取所有属性

        :return: 属性字典
        """
        return self.properties.copy()
    
    def to_string(self) -> str:
        """
        将Properties转换为字符串

        :return: Properties字符串
        """
        lines = []
        for key, value in self.properties.items():
            lines.append(f"{key}={value}\n")
        return ''.join(lines)
    
    def get_comment(self, key: str) -> Optional[str]:
        """
        获取指定键的注释

        :param key: 键
        :return: 注释
        """
        # 在实际的实现中，我们需要更复杂的注释跟踪机制
        # 这里简化处理
        return None
    
    def set_comment(self, key: str, comment: str) -> None:
        """
        设置指定键的注释

        :param key: 键
        :param comment: 注释
        """
        # 在实际的实现中，我们需要更复杂的注释跟踪机制
        # 这里简化处理
        pass
    
    def merge_properties(self, other: 'PropertiesUtils') -> None:
        """
        合并另一个Properties文件

        :param other: 另一个PropertiesUtils实例
        """
        self.properties.update(other.get_properties())
    
    def get_size(self) -> int:
        """
        获取Properties数量

        :return: Properties数量
        """
        return len(self.properties)
    
    def clear(self) -> None:
        """
        清空所有Properties
        """
        self.properties.clear()
        self.comments.clear()
        self.lines.clear()
    
    def get_type(self, key: str) -> str:
        """
        获取指定键值的类型（始终返回"str"，因为Properties文件中所有值都是字符串）

        :param key: 键
        :return: 类型字符串
        """
        if self.has_key(key):
            return "str"
        return "None"
    
    def get_all_lines(self) -> List[str]:
        """
        获取所有行（包括注释和空行）

        :return: 所有行的列表
        """
        return self.lines.copy()
    
    def find_keys(self, pattern: str) -> List[str]:
        """
        根据模式查找键

        :param pattern: 正则表达式模式
        :return: 匹配的键列表
        """
        regex = re.compile(pattern)
        return [key for key in self.properties.keys() if regex.search(key)]
    
    def update_values(self, updates: Dict[str, str]) -> None:
        """
        批量更新值

        :param updates: 包含键值对的字典
        """
        self.properties.update(updates)
    
    @staticmethod
    def from_dict(data: Dict[str, str]) -> 'PropertiesUtils':
        """
        从字典创建PropertiesUtils实例

        :param data: 字典数据
        :return: PropertiesUtils实例
        """
        properties_utils = PropertiesUtils()
        properties_utils.properties = data.copy()
        return properties_utils
    
    @staticmethod
    def create_empty_properties() -> 'PropertiesUtils':
        """
        创建空的Properties文档

        :return: PropertiesUtils实例
        """
        return PropertiesUtils()
    
    @staticmethod
    def is_valid_properties(properties_string: str) -> bool:
        """
        检查字符串是否为有效的Properties格式

        :param properties_string: Properties字符串
        :return: 是否为有效的Properties
        """
        try:
            properties_utils = PropertiesUtils(properties_string=properties_string)
            return True
        except Exception:
            return False